package org.jeecg.modules.wms.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.wms.entity.FinishedGoodsInventory;
import org.jeecg.modules.wms.mapper.FinishedGoodsInventoryMapper;
import org.jeecg.modules.wms.service.IFinishedGoodsInventoryLogService;
import org.jeecg.modules.wms.service.IFinishedGoodsInventoryService;
import org.jeecg.modules.wms.vo.InventoryAdjustVO;
import org.jeecg.modules.wms.vo.InventoryQueryParam;
import org.jeecg.modules.wms.vo.CustomerInventoryGroup;
import org.jeecg.modules.wms.vo.HierarchicalInventoryQueryParam;
import org.jeecg.modules.wms.vo.InventoryStatisticsVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 成品库存管理Service实现类
 */
@Slf4j
@Service
public class FinishedGoodsInventoryServiceImpl extends ServiceImpl<FinishedGoodsInventoryMapper, FinishedGoodsInventory> 
        implements IFinishedGoodsInventoryService {

    @Autowired
    private FinishedGoodsInventoryMapper inventoryMapper;
    
    @Autowired
    private IFinishedGoodsInventoryLogService inventoryLogService;

    @Override
    public IPage<FinishedGoodsInventory> queryInventoryList(IPage<FinishedGoodsInventory> page, InventoryQueryParam param) {
        return inventoryMapper.queryInventoryList((Page<FinishedGoodsInventory>) page, param);
    }

    @Override
    public List<FinishedGoodsInventory> queryInventoryByOrder(String orderNo) {
        if (oConvertUtils.isEmpty(orderNo)) {
            throw new JeecgBootException("订单号不能为空");
        }
        return inventoryMapper.queryInventoryByOrder(orderNo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void adjustInventory(InventoryAdjustVO adjustVO) {
        // 获取库存记录
        FinishedGoodsInventory inventory = this.getById(adjustVO.getInventoryId());
        if (inventory == null) {
            throw new JeecgBootException("库存记录不存在");
        }

        int beforeQuantity = inventory.getAvailableQuantity();
        int afterQuantity;
        String operationReason = adjustVO.getAdjustReason();

        // 根据调整类型计算调整后数量
        if (adjustVO.getAdjustType() == 1) { // 增加
            afterQuantity = beforeQuantity + adjustVO.getAdjustQuantity();
        } else if (adjustVO.getAdjustType() == 2) { // 减少
            afterQuantity = beforeQuantity - adjustVO.getAdjustQuantity();
            if (afterQuantity < 0) {
                throw new JeecgBootException("调整后库存数量不能为负数");
            }
        } else {
            throw new JeecgBootException("无效的调整类型");
        }

        // 更新库存数量
        int totalQuantity = afterQuantity + inventory.getReservedQuantity();
        inventoryMapper.updateInventoryQuantity(adjustVO.getInventoryId(), afterQuantity, 
                                              inventory.getReservedQuantity(), totalQuantity);

        // 记录库存变动
        inventoryLogService.recordInventoryChange(
            adjustVO.getInventoryId(),
            inventory.getOrderNo(),
            3, // 调整操作
            adjustVO.getAdjustQuantity(),
            beforeQuantity,
            afterQuantity,
            operationReason,
            null,
            null // TODO: 获取当前操作员姓名
        );
    }

    @Override
    public List<InventoryStatisticsVO> statisticsByWarehouse() {
        return inventoryMapper.statisticsByWarehouse();
    }

    @Override
    public List<InventoryStatisticsVO> statisticsByOrder() {
        return inventoryMapper.statisticsByOrder();
    }

    @Override
    public List<InventoryStatisticsVO> statisticsByWindowSeries() {
        return inventoryMapper.statisticsByWindowSeries();
    }

    @Override
    public InventoryStatisticsVO getInventoryOverview() {
        return inventoryMapper.getInventoryOverview();
    }

    @Override
    public List<FinishedGoodsInventory> queryLowStockWarning(Integer threshold) {
        if (threshold == null || threshold < 0) {
            threshold = 10; // 默认阈值
        }
        return inventoryMapper.queryLowStockWarning(threshold);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean reserveInventory(String inventoryId, Integer quantity, String reason) {
        FinishedGoodsInventory inventory = this.getById(inventoryId);
        if (inventory == null) {
            throw new JeecgBootException("库存记录不存在");
        }

        if (inventory.getAvailableQuantity() < quantity) {
            throw new JeecgBootException("可用库存不足，无法预留");
        }

        int newAvailableQuantity = inventory.getAvailableQuantity() - quantity;
        int newReservedQuantity = inventory.getReservedQuantity() + quantity;

        inventoryMapper.updateInventoryQuantity(inventoryId, newAvailableQuantity, 
                                              newReservedQuantity, inventory.getTotalQuantity());

        // 记录库存变动
        inventoryLogService.recordInventoryChange(
            inventoryId,
            inventory.getOrderNo(),
            4, // 预留操作
            quantity,
            inventory.getAvailableQuantity(),
            newAvailableQuantity,
            reason,
            null,
            null
        );

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean releaseReservedInventory(String inventoryId, Integer quantity, String reason) {
        FinishedGoodsInventory inventory = this.getById(inventoryId);
        if (inventory == null) {
            throw new JeecgBootException("库存记录不存在");
        }

        if (inventory.getReservedQuantity() < quantity) {
            throw new JeecgBootException("预留库存不足，无法释放");
        }

        int newAvailableQuantity = inventory.getAvailableQuantity() + quantity;
        int newReservedQuantity = inventory.getReservedQuantity() - quantity;

        inventoryMapper.updateInventoryQuantity(inventoryId, newAvailableQuantity, 
                                              newReservedQuantity, inventory.getTotalQuantity());

        // 记录库存变动
        inventoryLogService.recordInventoryChange(
            inventoryId,
            inventory.getOrderNo(),
            5, // 释放操作
            quantity,
            inventory.getAvailableQuantity(),
            newAvailableQuantity,
            reason,
            null,
            null
        );

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deductInventory(String inventoryId, Integer quantity, String relatedDocNo) {
        FinishedGoodsInventory inventory = this.getById(inventoryId);
        if (inventory == null) {
            throw new JeecgBootException("库存记录不存在");
        }

        if (inventory.getAvailableQuantity() < quantity) {
            throw new JeecgBootException("可用库存不足，无法扣减");
        }

        int newAvailableQuantity = inventory.getAvailableQuantity() - quantity;
        int newTotalQuantity = inventory.getTotalQuantity() - quantity;

        inventoryMapper.updateInventoryQuantity(inventoryId, newAvailableQuantity, 
                                              inventory.getReservedQuantity(), newTotalQuantity);

        // 记录库存变动
        inventoryLogService.recordInventoryChange(
            inventoryId,
            inventory.getOrderNo(),
            2, // 出库操作
            quantity,
            inventory.getAvailableQuantity(),
            newAvailableQuantity,
            "出库扣减",
            relatedDocNo,
            null
        );

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addInventory(String inventoryId, Integer quantity, String relatedDocNo) {
        FinishedGoodsInventory inventory = this.getById(inventoryId);
        if (inventory == null) {
            throw new JeecgBootException("库存记录不存在");
        }

        int newAvailableQuantity = inventory.getAvailableQuantity() + quantity;
        int newTotalQuantity = inventory.getTotalQuantity() + quantity;

        inventoryMapper.updateInventoryQuantity(inventoryId, newAvailableQuantity, 
                                              inventory.getReservedQuantity(), newTotalQuantity);

        // 记录库存变动
        inventoryLogService.recordInventoryChange(
            inventoryId,
            inventory.getOrderNo(),
            1, // 入库操作
            quantity,
            inventory.getAvailableQuantity(),
            newAvailableQuantity,
            "入库增加",
            relatedDocNo,
            null
        );

        return true;
    }

    @Override
    public IPage<FinishedGoodsInventory> queryInventoryForMobile(IPage<FinishedGoodsInventory> page, InventoryQueryParam param) {
        return baseMapper.queryInventoryForMobile(page, param);
    }

    @Override
    public List<CustomerInventoryGroup> queryHierarchicalInventoryForMobile(HierarchicalInventoryQueryParam param) {
        return baseMapper.queryHierarchicalInventoryForMobile(param);
    }

    @Override
    public IPage<CustomerInventoryGroup> queryHierarchicalInventoryForWeb(IPage<CustomerInventoryGroup> page, HierarchicalInventoryQueryParam param) {
        return baseMapper.queryHierarchicalInventoryForWeb(page, param);
    }

    @Override
    public List<FinishedGoodsInventory> queryByOrderDetailId(String orderDetailId) {
        return inventoryMapper.queryByOrderDetailId(orderDetailId);
    }

    @Override
    public Long getFinishedGoodsInboundOrderCount() {
        try {
            // 通过Mapper查询成品入库单总数
            return inventoryMapper.getFinishedGoodsInboundOrderCount();
        } catch (Exception e) {
            log.error("获取成品入库单总数失败", e);
            return 0L;
        }
    }

    @Override
    public Long getFinishedGoodsOutboundOrderCount() {
        try {
            // 通过Mapper查询成品出库单总数
            return inventoryMapper.getFinishedGoodsOutboundOrderCount();
        } catch (Exception e) {
            log.error("获取成品出库单总数失败", e);
            return 0L;
        }
    }
}
